home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / qmenu.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-13  |  15.5 KB  |  669 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. #include <string.h>
  21. #include <ctype.h>
  22.  
  23. #include "client.h"
  24. #include "qmenu.h"
  25.  
  26. static void     Action_DoEnter( menuaction_s *a );
  27. static void     Action_Draw( menuaction_s *a );
  28. static void  Menu_DrawStatusBar( const char *string );
  29. static void     Menulist_DoEnter( menulist_s *l );
  30. static void     MenuList_Draw( menulist_s *l );
  31. static void     Separator_Draw( menuseparator_s *s );
  32. static void     Slider_DoSlide( menuslider_s *s, int dir );
  33. static void     Slider_Draw( menuslider_s *s );
  34. static void     SpinControl_DoEnter( menulist_s *s );
  35. static void     SpinControl_Draw( menulist_s *s );
  36. static void     SpinControl_DoSlide( menulist_s *s, int dir );
  37.  
  38. #define RCOLUMN_OFFSET  16
  39. #define LCOLUMN_OFFSET -16
  40.  
  41. #define VID_WIDTH viddef.width
  42. #define VID_HEIGHT viddef.height
  43.  
  44. void Action_DoEnter( menuaction_s *a )
  45. {
  46.     if ( a->generic.callback )
  47.         a->generic.callback( a );
  48. }
  49.  
  50. void Action_Draw( menuaction_s *a )
  51. {
  52.     if ( a->generic.flags & QMF_LEFT_JUSTIFY )
  53.     {
  54.         if ( a->generic.flags & QMF_GRAYED )
  55.             Menu_DrawStringDark( a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET, a->generic.y + a->generic.parent->y, a->generic.name );
  56.         else
  57.             Menu_DrawString( a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET, a->generic.y + a->generic.parent->y, a->generic.name );
  58.     }
  59.     else
  60.     {
  61.         if ( a->generic.flags & QMF_GRAYED )
  62.             Menu_DrawStringR2LDark( a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET, a->generic.y + a->generic.parent->y, a->generic.name );
  63.         else
  64.             Menu_DrawStringR2L( a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET, a->generic.y + a->generic.parent->y, a->generic.name );
  65.     }
  66.     if ( a->generic.ownerdraw )
  67.         a->generic.ownerdraw( a );
  68. }
  69.  
  70. qboolean Field_DoEnter( menufield_s *f )
  71. {
  72.     if ( f->generic.callback )
  73.     {
  74.         f->generic.callback( f );
  75.         return true;
  76.     }
  77.     return false;
  78. }
  79.  
  80. void Field_Draw( menufield_s *f )
  81. {
  82.     int i;
  83.     char tempbuffer[128]="";
  84.  
  85.     if ( f->generic.name )
  86.         Menu_DrawStringR2LDark( f->generic.x + f->generic.parent->x + LCOLUMN_OFFSET, f->generic.y + f->generic.parent->y, f->generic.name );
  87.  
  88.     strncpy( tempbuffer, f->buffer + f->visible_offset, f->visible_length );
  89.  
  90.     Draw_Char( f->generic.x + f->generic.parent->x + 16, f->generic.y + f->generic.parent->y - 4, 18 );
  91.     Draw_Char( f->generic.x + f->generic.parent->x + 16, f->generic.y + f->generic.parent->y + 4, 24 );
  92.  
  93.     Draw_Char( f->generic.x + f->generic.parent->x + 24 + f->visible_length * 8, f->generic.y + f->generic.parent->y - 4, 20 );
  94.     Draw_Char( f->generic.x + f->generic.parent->x + 24 + f->visible_length * 8, f->generic.y + f->generic.parent->y + 4, 26 );
  95.  
  96.     for ( i = 0; i < f->visible_length; i++ )
  97.     {
  98.         Draw_Char( f->generic.x + f->generic.parent->x + 24 + i * 8, f->generic.y + f->generic.parent->y - 4, 19 );
  99.         Draw_Char( f->generic.x + f->generic.parent->x + 24 + i * 8, f->generic.y + f->generic.parent->y + 4, 25 );
  100.     }
  101.  
  102.     Menu_DrawString( f->generic.x + f->generic.parent->x + 24, f->generic.y + f->generic.parent->y, tempbuffer );
  103.  
  104.     if ( Menu_ItemAtCursor( f->generic.parent ) == f )
  105.     {
  106.         int offset;
  107.  
  108.         if ( f->visible_offset )
  109.             offset = f->visible_length;
  110.         else
  111.             offset = f->cursor;
  112.  
  113.         if ( ( ( int ) ( Sys_Milliseconds() / 250 ) ) & 1 )
  114.         {
  115.             Draw_Char( f->generic.x + f->generic.parent->x + ( offset + 2 ) * 8 + 8,
  116.                        f->generic.y + f->generic.parent->y,
  117.                        11 );
  118.         }
  119.         else
  120.         {
  121.             Draw_Char( f->generic.x + f->generic.parent->x + ( offset + 2 ) * 8 + 8,
  122.                        f->generic.y + f->generic.parent->y,
  123.                        ' ' );
  124.         }
  125.     }
  126. }
  127.  
  128. qboolean Field_Key( menufield_s *f, int key )
  129. {
  130.     extern int keydown[];
  131.  
  132.     switch ( key )
  133.     {
  134.     case K_KP_SLASH:
  135.         key = '/';
  136.         break;
  137.     case K_KP_MINUS:
  138.         key = '-';
  139.         break;
  140.     case K_KP_PLUS:
  141.         key = '+';
  142.         break;
  143.     case K_KP_HOME:
  144.         key = '7';
  145.         break;
  146.     case K_KP_UPARROW:
  147.         key = '8';
  148.         break;
  149.     case K_KP_PGUP:
  150.         key = '9';
  151.         break;
  152.     case K_KP_LEFTARROW:
  153.         key = '4';
  154.         break;
  155.     case K_KP_5:
  156.         key = '5';
  157.         break;
  158.     case K_KP_RIGHTARROW:
  159.         key = '6';
  160.         break;
  161.     case K_KP_END:
  162.         key = '1';
  163.         break;
  164.     case K_KP_DOWNARROW:
  165.         key = '2';
  166.         break;
  167.     case K_KP_PGDN:
  168.         key = '3';
  169.         break;
  170.     case K_KP_INS:
  171.         key = '0';
  172.         break;
  173.     case K_KP_DEL:
  174.         key = '.';
  175.         break;
  176.     }
  177.  
  178.     if ( key > 127 )
  179.     {
  180.         switch ( key )
  181.         {
  182.         case K_DEL:
  183.         default:
  184.             return false;
  185.         }
  186.     }
  187.  
  188.     /*
  189.     ** support pasting from the clipboard
  190.     */
  191.     if ( ( toupper( key ) == 'V' && keydown[K_CTRL] ) ||
  192.          ( ( ( key == K_INS ) || ( key == K_KP_INS ) ) && keydown[K_SHIFT] ) )
  193.     {
  194.         char *cbd;
  195.         
  196.         if ( ( cbd = Sys_GetClipboardData() ) != 0 )
  197.         {
  198.             strtok( cbd, "\n\r\b" );
  199.  
  200.             strncpy( f->buffer, cbd, f->length - 1 );
  201.             f->cursor = strlen( f->buffer );
  202.             f->visible_offset = f->cursor - f->visible_length;
  203.             if ( f->visible_offset < 0 )
  204.                 f->visible_offset = 0;
  205.  
  206.             free( cbd );
  207.         }
  208.         return true;
  209.     }
  210.  
  211.     switch ( key )
  212.     {
  213.     case K_KP_LEFTARROW:
  214.     case K_LEFTARROW:
  215.     case K_BACKSPACE:
  216.         if ( f->cursor > 0 )
  217.         {
  218.             memmove( &f->buffer[f->cursor-1], &f->buffer[f->cursor], strlen( &f->buffer[f->cursor] ) + 1 );
  219.             f->cursor--;
  220.  
  221.             if ( f->visible_offset )
  222.             {
  223.                 f->visible_offset--;
  224.             }
  225.         }
  226.         break;
  227.  
  228.     case K_KP_DEL:
  229.     case K_DEL:
  230.         memmove( &f->buffer[f->cursor], &f->buffer[f->cursor+1], strlen( &f->buffer[f->cursor+1] ) + 1 );
  231.         break;
  232.  
  233.     case K_KP_ENTER:
  234.     case K_ENTER:
  235.     case K_ESCAPE:
  236.     case K_TAB:
  237.         return false;
  238.  
  239.     case K_SPACE:
  240.     default:
  241.         if ( !isdigit( key ) && ( f->generic.flags & QMF_NUMBERSONLY ) )
  242.             return false;
  243.  
  244.         if ( f->cursor < f->length )
  245.         {
  246.             f->buffer[f->cursor++] = key;
  247.             f->buffer[f->cursor] = 0;
  248.  
  249.             if ( f->cursor > f->visible_length )
  250.             {
  251.                 f->visible_offset++;
  252.             }
  253.         }
  254.     }
  255.  
  256.     return true;
  257. }
  258.  
  259. void Menu_AddItem( menuframework_s *menu, void *item )
  260. {
  261.     if ( menu->nitems == 0 )
  262.         menu->nslots = 0;
  263.  
  264.     if ( menu->nitems < MAXMENUITEMS )
  265.     {
  266.         menu->items[menu->nitems] = item;
  267.         ( ( menucommon_s * ) menu->items[menu->nitems] )->parent = menu;
  268.         menu->nitems++;
  269.     }
  270.  
  271.     menu->nslots = Menu_TallySlots( menu );
  272. }
  273.  
  274. /*
  275. ** Menu_AdjustCursor
  276. **
  277. ** This function takes the given menu, the direction, and attempts
  278. ** to adjust the menu's cursor so that it's at the next available
  279. ** slot.
  280. */
  281. void Menu_AdjustCursor( menuframework_s *m, int dir )
  282. {
  283.     menucommon_s *citem;
  284.  
  285.     /*
  286.     ** see if it's in a valid spot
  287.     */
  288.     if ( m->cursor >= 0 && m->cursor < m->nitems )
  289.     {
  290.         if ( ( citem = Menu_ItemAtCursor( m ) ) != 0 )
  291.         {
  292.             if ( citem->type != MTYPE_SEPARATOR )
  293.                 return;
  294.         }
  295.     }
  296.  
  297.     /*
  298.     ** it's not in a valid spot, so crawl in the direction indicated until we
  299.     ** find a valid spot
  300.     */
  301.     if ( dir == 1 )
  302.     {
  303.         while ( 1 )
  304.         {
  305.             citem = Menu_ItemAtCursor( m );
  306.             if ( citem )
  307.                 if ( citem->type != MTYPE_SEPARATOR )
  308.                     break;
  309.             m->cursor += dir;
  310.             if ( m->cursor >= m->nitems )
  311.                 m->cursor = 0;
  312.         }
  313.     }
  314.     else
  315.     {
  316.         while ( 1 )
  317.         {
  318.             citem = Menu_ItemAtCursor( m );
  319.             if ( citem )
  320.                 if ( citem->type != MTYPE_SEPARATOR )
  321.                     break;
  322.             m->cursor += dir;
  323.             if ( m->cursor < 0 )
  324.                 m->cursor = m->nitems - 1;
  325.         }
  326.     }
  327. }
  328.  
  329. void Menu_Center( menuframework_s *menu )
  330. {
  331.     int height;
  332.  
  333.     height = ( ( menucommon_s * ) menu->items[menu->nitems-1])->y;
  334.     height += 10;
  335.  
  336.     menu->y = ( VID_HEIGHT - height ) / 2;
  337. }
  338.  
  339. void Menu_Draw( menuframework_s *menu )
  340. {
  341.     int i;
  342.     menucommon_s *item;
  343.  
  344.     /*
  345.     ** draw contents
  346.     */
  347.     for ( i = 0; i < menu->nitems; i++ )
  348.     {
  349.         switch ( ( ( menucommon_s * ) menu->items[i] )->type )
  350.         {
  351.         case MTYPE_FIELD:
  352.             Field_Draw( ( menufield_s * ) menu->items[i] );
  353.             break;
  354.         case MTYPE_SLIDER:
  355.             Slider_Draw( ( menuslider_s * ) menu->items[i] );
  356.             break;
  357.         case MTYPE_LIST:
  358.             MenuList_Draw( ( menulist_s * ) menu->items[i] );
  359.             break;
  360.         case MTYPE_SPINCONTROL:
  361.             SpinControl_Draw( ( menulist_s * ) menu->items[i] );
  362.             break;
  363.         case MTYPE_ACTION:
  364.             Action_Draw( ( menuaction_s * ) menu->items[i] );
  365.             break;
  366.         case MTYPE_SEPARATOR:
  367.             Separator_Draw( ( menuseparator_s * ) menu->items[i] );
  368.             break;
  369.         }
  370.     }
  371.  
  372.     item = Menu_ItemAtCursor( menu );
  373.  
  374.     if ( item && item->cursordraw )
  375.     {
  376.         item->cursordraw( item );
  377.     }
  378.     else if ( menu->cursordraw )
  379.     {
  380.         menu->cursordraw( menu );
  381.     }
  382.     else if ( item && item->type != MTYPE_FIELD )
  383.     {
  384.         if ( item->flags & QMF_LEFT_JUSTIFY )
  385.         {
  386.             Draw_Char( menu->x + item->x - 24 + item->cursor_offset, menu->y + item->y, 12 + ( ( int ) ( Sys_Milliseconds()/250 ) & 1 ) );
  387.         }
  388.         else
  389.         {
  390.             Draw_Char( menu->x + item->cursor_offset, menu->y + item->y, 12 + ( ( int ) ( Sys_Milliseconds()/250 ) & 1 ) );
  391.         }
  392.     }
  393.  
  394.     if ( item )
  395.     {
  396.         if ( item->statusbarfunc )
  397.             item->statusbarfunc( ( void * ) item );
  398.         else if ( item->statusbar )
  399.             Menu_DrawStatusBar( item->statusbar );
  400.         else
  401.             Menu_DrawStatusBar( menu->statusbar );
  402.  
  403.     }
  404.     else
  405.     {
  406.         Menu_DrawStatusBar( menu->statusbar );
  407.     }
  408. }
  409.  
  410. void Menu_DrawStatusBar( const char *string )
  411. {
  412.     if ( string )
  413.     {
  414.         int l = strlen( string );
  415.         int maxrow = VID_HEIGHT / 8;
  416.         int maxcol = VID_WIDTH / 8;
  417.         int col = maxcol / 2 - l / 2;
  418.  
  419.         Draw_Fill( 0, VID_HEIGHT-8, VID_WIDTH, 8, 4 );
  420.         Menu_DrawString( col*8, VID_HEIGHT - 8, string );
  421.     }
  422.     else
  423.     {
  424.         Draw_Fill( 0, VID_HEIGHT-8, VID_WIDTH, 8, 0 );
  425.     }
  426. }
  427.  
  428. void Menu_DrawString( int x, int y, const char *string )
  429. {
  430.     unsigned i;
  431.  
  432.     for ( i = 0; i < strlen( string ); i++ )
  433.     {
  434.         Draw_Char( ( x + i*8 ), y, string[i] );
  435.     }
  436. }
  437.  
  438. void Menu_DrawStringDark( int x, int y, const char *string )
  439. {
  440.     unsigned i;
  441.  
  442.     for ( i = 0; i < strlen( string ); i++ )
  443.     {
  444.         Draw_Char( ( x + i*8 ), y, string[i] + 128 );
  445.     }
  446. }
  447.  
  448. void Menu_DrawStringR2L( int x, int y, const char *string )
  449. {
  450.     unsigned i;
  451.  
  452.     for ( i = 0; i < strlen( string ); i++ )
  453.     {
  454.         Draw_Char( ( x - i*8 ), y, string[strlen(string)-i-1] );
  455.     }
  456. }
  457.  
  458. void Menu_DrawStringR2LDark( int x, int y, const char *string )
  459. {
  460.     unsigned i;
  461.  
  462.     for ( i = 0; i < strlen( string ); i++ )
  463.     {
  464.         Draw_Char( ( x - i*8 ), y, string[strlen(string)-i-1]+128 );
  465.     }
  466. }
  467.  
  468. void *Menu_ItemAtCursor( menuframework_s *m )
  469. {
  470.     if ( m->cursor < 0 || m->cursor >= m->nitems )
  471.         return 0;
  472.  
  473.     return m->items[m->cursor];
  474. }
  475.  
  476. qboolean Menu_SelectItem( menuframework_s *s )
  477. {
  478.     menucommon_s *item = ( menucommon_s * ) Menu_ItemAtCursor( s );
  479.  
  480.     if ( item )
  481.     {
  482.         switch ( item->type )
  483.         {
  484.         case MTYPE_FIELD:
  485.             return Field_DoEnter( ( menufield_s * ) item ) ;
  486.         case MTYPE_ACTION:
  487.             Action_DoEnter( ( menuaction_s * ) item );
  488.             return true;
  489.         case MTYPE_LIST:
  490. //            Menulist_DoEnter( ( menulist_s * ) item );
  491.             return false;
  492.         case MTYPE_SPINCONTROL:
  493. //            SpinControl_DoEnter( ( menulist_s * ) item );
  494.             return false;
  495.         }
  496.     }
  497.     return false;
  498. }
  499.  
  500. void Menu_SetStatusBar( menuframework_s *m, const char *string )
  501. {
  502.     m->statusbar = string;
  503. }
  504.  
  505. void Menu_SlideItem( menuframework_s *s, int dir )
  506. {
  507.     menucommon_s *item = ( menucommon_s * ) Menu_ItemAtCursor( s );
  508.  
  509.     if ( item )
  510.     {
  511.         switch ( item->type )
  512.         {
  513.         case MTYPE_SLIDER:
  514.             Slider_DoSlide( ( menuslider_s * ) item, dir );
  515.             break;
  516.         case MTYPE_SPINCONTROL:
  517.             SpinControl_DoSlide( ( menulist_s * ) item, dir );
  518.             break;
  519.         }
  520.     }
  521. }
  522.  
  523. int Menu_TallySlots( menuframework_s *menu )
  524. {
  525.     int i;
  526.     int total = 0;
  527.  
  528.     for ( i = 0; i < menu->nitems; i++ )
  529.     {
  530.         if ( ( ( menucommon_s * ) menu->items[i] )->type == MTYPE_LIST )
  531.         {
  532.             int nitems = 0;
  533.             const char **n = ( ( menulist_s * ) menu->items[i] )->itemnames;
  534.  
  535.             while (*n)
  536.                 nitems++, n++;
  537.  
  538.             total += nitems;
  539.         }
  540.         else
  541.         {
  542.             total++;
  543.         }
  544.     }
  545.  
  546.     return total;
  547. }
  548.  
  549. void Menulist_DoEnter( menulist_s *l )
  550. {
  551.     int start;
  552.  
  553.     start = l->generic.y / 10 + 1;
  554.  
  555.     l->curvalue = l->generic.parent->cursor - start;
  556.  
  557.     if ( l->generic.callback )
  558.         l->generic.callback( l );
  559. }
  560.  
  561. void MenuList_Draw( menulist_s *l )
  562. {
  563.     const char **n;
  564.     int y = 0;
  565.  
  566.     Menu_DrawStringR2LDark( l->generic.x + l->generic.parent->x + LCOLUMN_OFFSET, l->generic.y + l->generic.parent->y, l->generic.name );
  567.  
  568.     n = l->itemnames;
  569.  
  570.       Draw_Fill( l->generic.x - 112 + l->generic.parent->x, l->generic.parent->y + l->generic.y + l->curvalue*10 + 10, 128, 10, 16 );
  571.     while ( *n )
  572.     {
  573.         Menu_DrawStringR2LDark( l->generic.x + l->generic.parent->x + LCOLUMN_OFFSET, l->generic.y + l->generic.parent->y + y + 10, *n );
  574.  
  575.         n++;
  576.         y += 10;
  577.     }
  578. }
  579.  
  580. void Separator_Draw( menuseparator_s *s )
  581. {
  582.     if ( s->generic.name )
  583.         Menu_DrawStringR2LDark( s->generic.x + s->generic.parent->x, s->generic.y + s->generic.parent->y, s->generic.name );
  584. }
  585.  
  586. void Slider_DoSlide( menuslider_s *s, int dir )
  587. {
  588.     s->curvalue += dir;
  589.  
  590.     if ( s->curvalue > s->maxvalue )
  591.         s->curvalue = s->maxvalue;
  592.     else if ( s->curvalue < s->minvalue )
  593.         s->curvalue = s->minvalue;
  594.  
  595.     if ( s->generic.callback )
  596.         s->generic.callback( s );
  597. }
  598.  
  599. #define SLIDER_RANGE 10
  600.  
  601. void Slider_Draw( menuslider_s *s )
  602. {
  603.     int    i;
  604.  
  605.     Menu_DrawStringR2LDark( s->generic.x + s->generic.parent->x + LCOLUMN_OFFSET,
  606.                         s->generic.y + s->generic.parent->y, 
  607.                         s->generic.name );
  608.  
  609.     s->range = ( s->curvalue - s->minvalue ) / ( float ) ( s->maxvalue - s->minvalue );
  610.  
  611.     if ( s->range < 0)
  612.         s->range = 0;
  613.     if ( s->range > 1)
  614.         s->range = 1;
  615.     Draw_Char( s->generic.x + s->generic.parent->x + RCOLUMN_OFFSET, s->generic.y + s->generic.parent->y, 128);
  616.     for ( i = 0; i < SLIDER_RANGE; i++ )
  617.         Draw_Char( RCOLUMN_OFFSET + s->generic.x + i*8 + s->generic.parent->x + 8, s->generic.y + s->generic.parent->y, 129);
  618.     Draw_Char( RCOLUMN_OFFSET + s->generic.x + i*8 + s->generic.parent->x + 8, s->generic.y + s->generic.parent->y, 130);
  619.     Draw_Char( ( int ) ( 8 + RCOLUMN_OFFSET + s->generic.parent->x + s->generic.x + (SLIDER_RANGE-1)*8 * s->range ), s->generic.y + s->generic.parent->y, 131);
  620. }
  621.  
  622. void SpinControl_DoEnter( menulist_s *s )
  623. {
  624.     s->curvalue++;
  625.     if ( s->itemnames[s->curvalue] == 0 )
  626.         s->curvalue = 0;
  627.  
  628.     if ( s->generic.callback )
  629.         s->generic.callback( s );
  630. }
  631.  
  632. void SpinControl_DoSlide( menulist_s *s, int dir )
  633. {
  634.     s->curvalue += dir;
  635.  
  636.     if ( s->curvalue < 0 )
  637.         s->curvalue = 0;
  638.     else if ( s->itemnames[s->curvalue] == 0 )
  639.         s->curvalue--;
  640.  
  641.     if ( s->generic.callback )
  642.         s->generic.callback( s );
  643. }
  644.  
  645. void SpinControl_Draw( menulist_s *s )
  646. {
  647.     char buffer[100];
  648.  
  649.     if ( s->generic.name )
  650.     {
  651.         Menu_DrawStringR2LDark( s->generic.x + s->generic.parent->x + LCOLUMN_OFFSET, 
  652.                             s->generic.y + s->generic.parent->y, 
  653.                             s->generic.name );
  654.     }
  655.     if ( !strchr( s->itemnames[s->curvalue], '\n' ) )
  656.     {
  657.         Menu_DrawString( RCOLUMN_OFFSET + s->generic.x + s->generic.parent->x, s->generic.y + s->generic.parent->y, s->itemnames[s->curvalue] );
  658.     }
  659.     else
  660.     {
  661.         strcpy( buffer, s->itemnames[s->curvalue] );
  662.         *strchr( buffer, '\n' ) = 0;
  663.         Menu_DrawString( RCOLUMN_OFFSET + s->generic.x + s->generic.parent->x, s->generic.y + s->generic.parent->y, buffer );
  664.         strcpy( buffer, strchr( s->itemnames[s->curvalue], '\n' ) + 1 );
  665.         Menu_DrawString( RCOLUMN_OFFSET + s->generic.x + s->generic.parent->x, s->generic.y + s->generic.parent->y + 10, buffer );
  666.     }
  667. }
  668.  
  669.